﻿using System;
using System.Linq;
using FitNesseRunner.Model;

namespace FitNesseRunner
{
	public class PageHandlerDispatcher : IPageObserver
	{
		private readonly IDirectiveHandler[] _directiveHandlers;
		private readonly ITableHandler[] _tableHandlers;
		private readonly ITableHandler _defaultHandler;
		private readonly IDispatcherReporter _reporter;

		public PageHandlerDispatcher(IDirectiveHandler[] directiveHandlers, ITableHandler[] tableHandlers, ITableHandler defaultHandler, IDispatcherReporter reporter = null)
		{
			_directiveHandlers = directiveHandlers;
			_tableHandlers = tableHandlers;
			_defaultHandler = defaultHandler;
			_reporter = reporter;
		}

		public void HandleDirective(IDirective directive)
		{
			foreach (var directiveHandler in _directiveHandlers.Where(x => x.DirectiveName == directive.Name))
			{
				HandleDirective(directive, directiveHandler);
			}
		}

		private void HandleDirective(IDirective directive, IDirectiveHandler directiveHandler)
		{
			try
			{
				directiveHandler.Handle(directive);
			}
			catch (Exception ex)
			{
				_reporter.ReportException(ex);
			}
		}

		public void HandleTable(ITable table)
		{
			var tableHandler = _tableHandlers.Where(handler => handler.CanHandle(table)).FirstOr(_defaultHandler);
			HandleTable(table, tableHandler);
		}

		private void HandleTable(ITable table, ITableHandler tableHandler)
		{
			try
			{
				tableHandler.Handle(table);
			}
			catch (Exception ex)
			{
				_reporter.ReportException(ex);
			}
		}
	}
}